﻿#region using
using System;
using System.Collections.Generic;
using System.Text;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Reflection;
using Janksen.Mapping.EntityExtend; 
#endregion

namespace Janksen.Mapping
{
    /// <summary>
    /// 生成实体扩展类
    /// </summary>
    internal class GenEntityExtend
    {
        #region 生成实体扩展类
        /// <summary>
        /// 生成实体扩展类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="objEntity"></param>
        /// <returns></returns>
        public static IEntityExtend GenExtendClass<T>()
        {
            // 创建编译器对象
            CSharpCodeProvider codeProvider = new CSharpCodeProvider();

            // 设置编译参数
            CompilerParameters options = new CompilerParameters();
            //引用系统命名空间文件
            options.ReferencedAssemblies.Add("System.dll");
            options.ReferencedAssemblies.Add("mscorlib.dll");
            options.ReferencedAssemblies.Add("System.Data.dll");
            //引用使用的文件
            options.ReferencedAssemblies.Add(typeof(Janksen.Mapping.EntityExtend.IEntityExtend).Assembly.Location);
            options.ReferencedAssemblies.Add(typeof(T).Assembly.Location);

            options.GenerateExecutable = false;
            options.GenerateInMemory = true;//内存中编译

            //类的代码
            StringBuilder code = new StringBuilder("");

            //引用命名空间
            code.AppendLine("using System;");
            code.AppendLine("using System.Collections.Generic;");
            code.AppendLine("using System.Text;");
            code.AppendLine("using System.Data;");
            code.AppendLine("using System.Data.SqlClient;");
            code.AppendLine("using Janksen.Mapping.EntityExtend;");
            code.AppendFormat("using {0};", typeof(T).Namespace);
            code.AppendLine("");

            code.Append("namespace Janksen.Mapping.EntityExtend");
            code.AppendLine("");
            code.AppendLine("{");

            PropertyInfo[] objPropetys = typeof(T).GetProperties();//获取类型的所有字段

            code.AppendFormat("public class {0}:IEntityExtend", typeof(T).Name);
            code.AppendLine("");
            code.AppendLine("{");

            //设置实体的字段的值方法（从DataRow获取值）
            code.AppendFormat("public object  SetFieldsValue(DataRow dr)");
            code.AppendLine("");
            code.AppendLine("{");
            code.AppendFormat("{0} obj=new {0}();", typeof(T).FullName);
            foreach (PropertyInfo property in objPropetys)
            {
                code.AppendFormat("if(dr[\"{0}\"]!=null)", property.Name);
                code.AppendLine("");
                code.AppendLine("{");
                code.AppendFormat("obj.{0}=({1})dr[\"{2}\"];", property.Name, property.PropertyType.FullName, property.Name);
                code.AppendLine("");
                code.AppendLine("}");
                //code.AppendLine("else");
                //code.AppendLine("{");
                //code.AppendLine("");
                //code.AppendLine("}");
            }
            code.AppendLine("return obj;");
            code.AppendLine("}");

            //设置实体的字段的值方法（从SqlDataReader获取值）
            code.AppendFormat("public object  SetFieldsValue(SqlDataReader dr)");
            code.AppendLine("");
            code.AppendLine("{");
            code.AppendFormat("{0} obj=new {0}();", typeof(T).FullName);
            foreach (PropertyInfo property in objPropetys)
            {
                code.AppendFormat("if(dr[\"{0}\"]!=null)", property.Name);
                code.AppendLine("");
                code.AppendLine("{");
                code.AppendFormat("obj.{0}=({1})dr[\"{2}\"];", property.Name, property.PropertyType.FullName, property.Name);
                code.AppendLine("");
                code.AppendLine("}");
                //code.AppendLine("else");
                //code.AppendLine("{");
                //code.AppendLine("");
                //code.AppendLine("}");
            }
            code.AppendLine("return obj;");
            code.AppendLine("}");

            //获取数据库参数方法
            code.AppendFormat(" public SqlParameter[] GetSqlParamsValue(object dataObj)");
            code.AppendLine("");
            code.AppendLine("{");
            code.AppendFormat("{0} entity=({0})dataObj;", typeof(T).FullName);
            code.AppendLine("");
            code.AppendFormat("List<SqlParameter> lstParams = new List<SqlParameter>();");
            foreach (PropertyInfo property in objPropetys)
            {
                code.AppendFormat("lstParams.Add(new SqlParameter(\"@{0}\",entity.{0}));", property.Name);
                code.AppendLine("");
            }
            code.AppendLine("return lstParams.ToArray();");
            code.AppendLine(@"
                        }
                     }
                   }");

            CodeSnippetCompileUnit cu = new CodeSnippetCompileUnit(code.ToString());

            // 开始编译
            CompilerResults cr = codeProvider.CompileAssemblyFromDom(options, cu);

            //如果编译发生错误
            if (cr.Errors.HasErrors)
            {
                throw new Exception(string.Format("在动态编译Janksen.Mapping.EntityExtend.{0}时发生错误：{1}{2}", typeof(T).Name, System.Environment.NewLine, cr.Errors[0].ErrorText));
            }

            //获取生成后的类实例
            object obj = cr.CompiledAssembly.CreateInstance("Janksen.Mapping.EntityExtend" + "." + typeof(T).Name);

            return (IEntityExtend)obj;
        } 
        #endregion
    }
}
